/*
 *
 *  * | Licensed 未经许可不能去掉「OPENIITA」相关版权
 *  * +----------------------------------------------------------------------
 *  * | Author: xw2sy@163.com
 *  * +----------------------------------------------------------------------
 *
 *  Copyright [2024] [OPENIITA]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * /
 */

package cc.iotkit.data.service;

import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.common.satoken.utils.LoginHelper;
import cc.iotkit.common.utils.MapstructUtils;
import cc.iotkit.common.utils.StringUtils;
import cc.iotkit.data.dao.BizWorkorderRepository;
import cc.iotkit.data.dao.IJPACommData;
import cc.iotkit.data.manager.IBizWorkorder;
import cc.iotkit.data.model.QTbSysDictData;
import cc.iotkit.data.model.TbBizWorkorder;
import cc.iotkit.data.model.TbSysDictData;
import cc.iotkit.data.util.PredicateBuilder;
import cc.iotkit.model.biz.BizWorkorder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.StringPath;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.ZoneId;
import java.util.List;

import static cc.iotkit.data.model.QTbBizWorkorder.tbBizWorkorder;
import static cc.iotkit.data.model.QTbBizWorkorderFailure.tbBizWorkorderFailure;
import static cc.iotkit.data.model.QTbBizWorkorderMaintenance.tbBizWorkorderMaintenance;
import static cc.iotkit.data.model.QTbDeviceInfo.tbDeviceInfo;
import static cc.iotkit.data.model.QTbProduct.tbProduct;
import static cc.iotkit.data.model.QTbProductModel.tbProductModel;
import static cc.iotkit.data.model.QTbSysDictData.tbSysDictData;
import static cc.iotkit.data.model.QTbSysUser.tbSysUser;

@Primary
@Service
public class BizWorkorderDataImpl implements IBizWorkorder, IJPACommData<BizWorkorder, Long> {
    @Autowired
    private JPAQueryFactory jpaQueryFactory;
    @Autowired
    private BizWorkorderRepository repository;

    @Override
    public JpaRepository getBaseRepository() {
        return repository;
    }

    @Override
    public Class getJpaRepositoryClass() {
        return TbBizWorkorder.class;
    }

    @Override
    public Class getTClass() {
        return BizWorkorder.class;
    }



    @Override
    public BizWorkorder findById(Long s) {
        BizWorkorder data=new BizWorkorder();
        data.setId(s);
        BizWorkorder result = buildSelect(data).fetchOne();
        return result;
        //return MapstructUtils.convert(repository.findById(s).orElse(null), BizWorkorder.class);
    }

    @Override
    public BizWorkorder save(BizWorkorder data) {
        //新增
        if (data.getId()==null||data.getId().equals(0L)) {
            data.setTenantId(Long.parseLong(LoginHelper.getTenantId()));
            data.setCreateDept(LoginHelper.getDeptId());
            data.setUid(LoginHelper.getUserId());
            data.setCreateAt(System.currentTimeMillis());
            data.setCreateBy(LoginHelper.getUserId());
            data.setCreateUser(LoginHelper.getUsername());
            //流水号
            String docNumber="GD"+System.currentTimeMillis();
            data.setDocNumber(docNumber);
        }else{
            data.setUpdateAt(System.currentTimeMillis());
            data.setUpdateBy(LoginHelper.getUserId());
            data.setCreateUser(LoginHelper.getUsername());
        }
        TbBizWorkorder result= repository.save(MapstructUtils.convert(data, TbBizWorkorder.class));
        return MapstructUtils.convert(result, BizWorkorder.class);
    }

    @Transactional
    public List<BizWorkorder> saveAll(List<BizWorkorder> datas) {
        /*for(BizWorkorder data : datas){
            //新增
            if (data.getId()==null||data.getId().equals(0L)) {
                data.setTenantId(Long.parseLong(LoginHelper.getTenantId()));
                data.setCreateDept(LoginHelper.getDeptId());
                data.setUid(LoginHelper.getUserId());
                data.setCreateAt(System.currentTimeMillis());
                data.setCreateBy(LoginHelper.getUserId());
                data.setCreateUser(LoginHelper.getUsername());
            }else{
                data.setUpdateAt(System.currentTimeMillis());
                data.setUpdateBy(LoginHelper.getUserId());
                data.setCreateUser(LoginHelper.getUsername());
            }

        }

        List<TbBizWorkorder> results= repository.saveAll(MapstructUtils.convert(datas, TbBizWorkorder.class));
        return MapstructUtils.convert(results, BizWorkorder.class); */
        return null;
    }

    @Override
    public List<BizWorkorder> findAll() {
        return MapstructUtils.convert(repository.findAll(), BizWorkorder.class);
    }
    private Predicate buildPredicate(BizWorkorder data) {
        Predicate cb =PredicateBuilder.instance()
                .and(data.getId()!=null,()->tbBizWorkorder.id.eq(data.getId()))
                .and(data.getProductId()!=null, () -> tbBizWorkorder.productId.eq(data.getProductId()))
                .and(data.getDeviceId()!=null, () -> tbBizWorkorder.deviceId.eq(data.getDeviceId()))
                .and(StringUtils.isNotEmpty(data.getProductName()), () -> tbProduct.name.like("%"+data.getProductName()+"%"))
                .and(StringUtils.isNotEmpty(data.getDeviceName()), () -> tbDeviceInfo.deviceName.like("%"+data.getDeviceName()+"%"))
                .and(StringUtils.isNotEmpty(data.getDocNumber()), () -> tbBizWorkorder.docNumber.like("%"+data.getDocNumber()+"%"))
                .and(StringUtils.isNotEmpty(data.getType()), () -> tbBizWorkorder.type.eq(data.getType()))
                .and(StringUtils.isNotEmpty(data.getStatus()), () -> tbBizWorkorder.status.eq(data.getStatus()))
                .and(data.getBeginTime()!=null, () -> tbBizWorkorder.createAt.goe(data.getBeginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()))
                .and(data.getEndTime()!=null, () -> tbBizWorkorder.createAt.loe(data.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()))
                .build();

        return cb;
    }
    public List<BizWorkorder> findAllByCondition(BizWorkorder query) {
        List<BizWorkorder> results = buildSelect(query).fetch();
        return results;

    }
    public Paging<BizWorkorder> findAllByConditions(PageRequest<BizWorkorder> pageRequest) {
        BizWorkorder data = pageRequest.getData();
        QueryResults<BizWorkorder> results = buildSelect(data).limit(pageRequest.getPageSize()).offset(pageRequest.getOffset()).fetchResults();
        return new Paging<>(results.getTotal(), results.getResults());
    }
    public JPAQuery<BizWorkorder> buildSelect(BizWorkorder data){
        Predicate predicate = buildPredicate(data);

        //可以查看自己或别人分配的工单
        PredicateBuilder cb =PredicateBuilder.instance();
        if(!LoginHelper.isSuperAdmin()) {
            cb.or(tbBizWorkorder.personId.eq(LoginHelper.getUserId()))
                    .or(tbBizWorkorder.uid.eq(LoginHelper.getUserId()));
        }
        Predicate predicate2 =cb.build();
        //关联多个相同表需要定义不同的别名
        QTbSysDictData tbSysDictDataType=new QTbSysDictData("tbSysDictDataType");
        QTbSysDictData tbSysDictDataStatus=new  QTbSysDictData("tbSysDictDataStatus");
        return jpaQueryFactory.select(Projections.bean(BizWorkorder.class,
                        tbBizWorkorder.id,tbBizWorkorder.docNumber,tbBizWorkorder.uid,tbBizWorkorder.createDept,tbBizWorkorder.tenantId,tbBizWorkorder.remark,tbBizWorkorder.createAt,tbBizWorkorder.createBy,
                        tbBizWorkorder.updateAt,tbBizWorkorder.updateBy,tbBizWorkorder.createUser,tbBizWorkorder.updateUser,
                        tbBizWorkorder.type,tbBizWorkorder.status,tbBizWorkorder.personId,tbBizWorkorder.result,tbBizWorkorder.productId,tbBizWorkorder.deviceId,
                        tbBizWorkorderFailure.failureDate,tbBizWorkorderFailure.affect,tbBizWorkorderMaintenance.maintenanceDate,
                        Expressions.as(tbSysDictDataType.dictLabel, Expressions.stringPath("typeName")),
                        Expressions.as(tbSysDictDataStatus.dictLabel, Expressions.stringPath("statusName")),
                        Expressions.as(tbProduct.name, Expressions.stringPath("productName")),tbProduct.productKey,
                        tbDeviceInfo.deviceName,tbDeviceInfo.robotSn,tbDeviceInfo.modelId,Expressions.as(tbProductModel.model, Expressions.stringPath("modelName")),
                        Expressions.as(tbSysUser.nickName, Expressions.stringPath("personName"))
                ))
                .from(tbBizWorkorder)
                .leftJoin(tbBizWorkorderFailure).on(tbBizWorkorderFailure.pid.eq(tbBizWorkorder.id))
                .leftJoin(tbBizWorkorderMaintenance).on(tbBizWorkorderMaintenance.pid.eq(tbBizWorkorder.id))
                .leftJoin(tbSysDictDataType).on(tbSysDictDataType.dictType.eq("biz_workorder_type").and(tbSysDictDataType.dictValue.eq(tbBizWorkorder.type)))
                .leftJoin(tbProduct).on(tbProduct.id.eq(tbBizWorkorder.productId))
                .leftJoin(tbDeviceInfo).on(tbDeviceInfo.id.eq(tbBizWorkorder.deviceId))
                .leftJoin(tbProductModel).on(tbDeviceInfo.modelId.eq(tbProductModel.id))
                .leftJoin(tbSysUser).on(tbSysUser.id.eq(tbBizWorkorder.personId))
                .leftJoin(tbSysDictDataStatus).on(tbSysDictDataStatus.dictType.eq("biz_workorder_status").and(tbSysDictDataStatus.dictValue.eq(tbBizWorkorder.status)))
                .where(predicate).where(predicate2).orderBy(tbBizWorkorder.id.desc());
    }


}
